#include <cstdio>
#include <cstdlib>

// x86
#define __stack_chk() \
{ \
    int64_t canary; \
    __asm__ __volatile__( \
        "mov -0x8(%%rbp), %%rax\n" \
        "mov %%rax, %0\n" \
        : "=g"(canary) \
        : \
        : "rax", "memory" \
    ); \
    printf("%s<%d> canary: %016lx\n", __func__, __LINE__, canary); \
}

#define __stack_chk2() \
{ \
    int64_t canary; \
    __asm__ __volatile__( \
        "mov -0x0(%%rbp), %%rax\n" \
        "mov -0x8(%%rax), %%rax\n" \
        "mov %%rax, %0\n" \
        : "=g"(canary) \
        : \
        : "rax", "memory" \
    ); \
    printf("%s<%d> canary: %016lx\n", __func__, __LINE__, canary); \
}

// aarch64
// {
//     int64_t canary, now_canary;
//     __asm__ __volatile__ (
//         "mrs x0, tpidr_el0\n"
//         "ldr x0, [x0, #40]\n"
//         "str x0, %0\n"
//         "ldr x0, [sp, #8]\n"
//         "str x0, %1\n"
//         : "=g"(canary), "=g"(now_canary)
//         :: "x0", "memory"
//     );
// }
//
// {
//     int64_t canary, now_canary;
//     __asm__ __volatile__ (
//         "mrs x0, tpidr_el0\n"
//         "ldr x0, [x0, #40]\n"
//         "str x0, %0\n"
//         "ldr x0, [sp, #0]\n"
//         "ldr x0, [x0, #8]\n"
//         "str x0, %1\n"
//         : "=g"(canary), "=g"(now_canary)
//         :: "x0", "memory"
//     );
// }
//
// {
//     int64_t canary, now_canary;
//     __asm__ __volatile__ (
//         "mrs x0, tpidr_el0\n"
//         "ldr x0, [x0, #40]\n"
//         "str x0, %0\n"
//         "ldr x0, [sp, #0]\n"
//         "ldr x0, [x0, #0]\n"
//         "ldr x0, [x0, #8]\n"
//         "str x0, %1\n"
//         : "=g"(canary), "=g"(now_canary)
//         :: "x0", "memory"
//     );
// }

void write_stack()
{
    int64_t i = 0x345;
    __stack_chk2();
    *(&i + 18) = 0;
    __stack_chk2();
}

void func(int32_t a)
{
    int64_t i = 0x234;
    int64_t old_canary;
    __stack_chk();
    printf("%016lx\n", *(&i + 1));
    __stack_chk();
    old_canary = *(&i + 1);
    write_stack();
    *(&i + 1) = 0;
    __stack_chk();
    printf("%016lx\n", *(&i + 1));
    __stack_chk();
    *(&i + 1) = old_canary;
    __stack_chk();
}

int main()
{
    system("cat /proc/$(($$ - 1))/maps");
    func(0x123);
    return 0;
}
